home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / mus / midi / MusicXMagic.lha / MusicX-Magic.txt < prev    next >
Text File  |  1997-07-11  |  25KB  |  642 lines

  1.                 Music-X Magic:
  2.           Soup Up Your Sequencer With ARexx
  3.  
  4.          Copyright 1994 by Daniel J. Barrett
  5.                Email: dbarrett@ora.com
  6.  
  7.    ***  This article may be freely distributed, as long as it  ***
  8.    ***  is distributed in its entirety, without modification.  ***
  9.  
  10.     After a several year wait between updates, Music-X 2.0 finally
  11. arrived last Spring.  One of the significant changes is that the program
  12. now supports ARexx, the Amiga's inter-program communication language.  This
  13. is very good news:  you can now extend Music-X's capabilities in powerful
  14. ways by writing "scripts" that operate on your sequences. For example,
  15. scripts can count the number of musical events in a sequence, transpose
  16. your music in various ways, or perform algorithmic composition.  You can
  17. even make Music-X communicate with other ARexx compatible programs (more
  18. than 400 exist) to increase your power even further.  For example, you can
  19. send data from Music-X directly into Deluxe Music 2.0 for musical notation,
  20. or communicate with a statistical package to analyze your sequences.
  21.  
  22.     Unfortunately, the ARexx documentation for Music-X is very sketchy.
  23. The manual is brief, omits some vital facts, and the example scripts
  24. mentioned in the manual (page 22) were omitted from the program. This
  25. article clarifies the manual, reveals the missing information, and teaches
  26. you how to write several useful scripts.  This article assumes that you
  27. have at least looked at the ARexx chapter of the upgrade manual; keep it
  28. nearby for reference.
  29.  
  30.  
  31. A MOTIVATING EXAMPLE
  32.  
  33.     Let's begin with a simple script that transposes all the notes in
  34. your sequence upward by a perfect fifth (7 semitones).  The numbers 1-12 on
  35. the left side are not part of the script; they are for our reference only.
  36.  
  37.     1    /* Transpose up by a perfect fifth. */
  38.     2    OPTIONS RESULTS
  39.     3    BeginScan ALL
  40.     4    NextEvent
  41.     5    DO WHILE RESULT = 1
  42.     6        IF Event.Type = "NOTE" THEN DO
  43.     7            Event.Num = Event.Num + 7
  44.     8            ReplEvent
  45.     9        END
  46.     10        NextEvent
  47.     11    END
  48.     12    EndScan
  49.  
  50. Let's examine what each line means.
  51.  
  52.     1.    A comment.  Every ARexx script must begin with a comment;
  53.         this is required, or else the script will not work.
  54.     2.    Tell ARexx to report the results of certain commands in
  55.         a variable called "RESULT".  We need this variable on
  56.         line 5.
  57.     3.    Tell Music-X that we want to examine (scan through) all
  58.         the events in the current sequence.
  59.     4.    Read the first event.  Its data is automatically stored in
  60.         a special variable called "Event".
  61.     5-11.    This "loop" is the heart of the script.  As each event is
  62.         read, its type is checked.  If it is a NOTE event, add 7 to
  63.         its note number, and use "ReplEvent" to make the change
  64.         permanent.  No matter what, we move to the next event and
  65.         repeat.  When there are no more events, "NextEvent" will
  66.         fail, RESULT will equal zero (meaning failure), and the
  67.         loop ends.
  68.     12.    Tell Music-X we are done scanning the sequence.
  69.  
  70.     Type this script into a file called "Transposer.mxe".  Now load
  71. a sequence into the Bar Editor, choose "Rexx..." from the Modules menu,
  72. use the file requestor to locate your Transposer.mxe script, and double-click
  73. on the script name.  Voila!  Your notes have been transposed.
  74.  
  75.  
  76. BASIC CONCEPTS
  77.     
  78.     ARexx support in Music-X is handled by a new module called
  79. RexxEdit.  This module is automatically installed when you use the Music-X
  80. installation program.  However, due to a bug in the installation, all your
  81. modules may not be accessible due to incorrect path names.  If you
  82. encounter this, then exit Music-X, run the "Install Modules" program, click
  83. on each module name and remove the leading colon ":" from its Path, choose
  84. "Save", and restart Music-X.
  85.  
  86.     In a nutshell, RexxEdit allows you to do four kinds of operations:
  87.  
  88.     1. Examine, add, delete, and change data in sequences.
  89.     2. Display requestors with a variety of gadgets for user input.
  90.     3. Get information about the bar editor:  grid size,
  91.        selected regions, step size, etc.
  92.     4. Communicate with other ARexx-compatible programs.
  93.  
  94. In addition, RexxEdit does NOT allow you to:
  95.  
  96.     1. Control recording and playback.
  97.     2. Control the Tool List in the Bar and Event Editors.
  98.     3. Use the cut, copy, and paste features.
  99.     4. Display or hide events in the Bar and Event Editors.
  100.     5. Affect the controls on the Sequencer, Filters, Samples, and
  101.        Librarian pages.
  102.  
  103. Perhaps a later version of Music-X will support such operations; but given
  104. how long it took for the 2.0 update, I have my doubts.
  105.  
  106.  
  107. OPERATIONS ON SEQUENCES
  108.  
  109.     Scripts that operate on sequences typically look a lot like
  110. our "Transposer.mxe" example.  First, BeginScan must be called to examine
  111. the sequence. This is followed by a loop which examines each event using
  112. NextEvent and processes it in some way.  When NextEvent returns "0" in the
  113. RESULT variable, the loop is finished, and we call EndScan.
  114.  
  115.     If you plan to add events to a sequence using AddEvent, there is
  116. an undocumented step which you MUST do:  initialize the "Event" variable. 
  117. This is done by placing the line
  118.  
  119.                Event. = ""
  120.  
  121. once in your script, before any call to AddEvent.  Note that the
  122. period after "Event" is mandatory because it is a stem variable.  It
  123. doesn't matter what value you assign here; for example,
  124.  
  125.             Event. = 192873
  126.  
  127. will work equally well.
  128.  
  129.     As an example, let's modify Transposer.mxe so instead of moving
  130. the notes, it adds new notes 7 semitones above the originals.  For
  131. example, every C will get a new G added above it.  This requires two
  132. changes:  initialize the "Event" variable (say, between lines 2 and 3),
  133. and change the ReplEvent on line 8 to AddEvent.  Store the script in a new
  134. file called Interval.mxe and test it out.
  135.  
  136.  
  137. REQUESTORS AND USER INPUT
  138.  
  139.     Our Transposer.mxe script is useful but limited. What if you want
  140. to transpose notes by sevenths instead of fifths? Do we need a whole new
  141. script for every kind of transposition?  Nope!  In this section, we will
  142. add a requestor to Transposer.mxe with several gadgets, allowing user
  143. control over the script's behavior.
  144.  
  145.     RexxEdit can display three kinds of requestors: a file requestor
  146. (MXFile), a "tell the user" requestor (MXReport), and a gadget-filled
  147. requestor for user input (MXRequest).  The first two are well explained on
  148. page 46 of the upgrade manual.  Our example will use the more complicated
  149. MXRequest.  There are four steps to using it:
  150.  
  151.     1. Decide whether you want a 1-column or 2-column requestor,
  152.        using the MXColumn command.  (Optional.)
  153.  
  154.     2. Define your gadgets.  Your choices are:
  155.  
  156.         MXButton    On/Off buttons.
  157.         MXSlider    Sliders with positive values.
  158.         MXMirror    Sliders with negative and positive values.
  159.         MXString    String gadgets for text input.
  160.         MXNoteSize    The Music-X note duration control.
  161.         MXLabel        Plain text; not for user input.
  162.  
  163.     3. Display the requestor with the MXRequest command.
  164.  
  165.     4. Read the gadgets with the MXValue command to find out the user's
  166.        selections.
  167.  
  168.     Our example lets the user choose a transposition interval, whether
  169. to replace or add notes, and whether to affect all notes or just
  170. selected/marked notes.  First, let's design the requestor.
  171.  
  172.     1    /* A requestor for transposing. */
  173.     2    OPTIONS RESULTS
  174.     3    MXMirror "Semitones:,127"
  175.     4    MXRadio "Replace existing notes,Add new notes"
  176.     5    MXRadio "All notes,Selected notes only"
  177.     6    MXRequest "My Transposer"
  178.  
  179. Lines 3-5 define three gadgets:  a "Semitones" slider running from -127 to
  180. +127, a pair of buttons for choosing replace or add, and another pair of
  181. buttons for choosing all or selected notes.  Line 6 actually displays the
  182. requestor with our gadgets, as shown in Figure 1.  To display it yourself,
  183. save lines 1-5 in a script called "Requestor.mxe" and execute it.  Play
  184. around with the gadgets all you like, but remember that this requestor will
  185. have no actual effect on your sequence... yet.
  186.  
  187.     Continuing, let's find out what the user chose to do.  If the
  188. user clicked CANCEL, the RESULT variable will have value 0.  If so,
  189. we choose to exit immediately:
  190.  
  191.     7    IF RESULT = 0 THEN
  192.     8        EXIT
  193.  
  194.     Next, we check our three defined gadgets using MXValue. To read the
  195. first gadget, use "MXValue 1"; for the second, "MXValue 2"; etc. The gadget
  196. value is returned in the RESULT variable.  For "Semitones" slider, we store
  197. the results in a variable "semitones":
  198.  
  199.     9    MXValue 1
  200.     10    semitones = RESULT
  201.  
  202. The "add/replace" radio buttons have value 0 if the first button was
  203. chosen, or a 1 for the second button:
  204.  
  205.     11    MXValue 2
  206.     12    add = RESULT
  207.  
  208. For the "all/selected events" buttons, we set the variable "scanType" to
  209. "ALL" or "SELECTED" appropriately.  These words have special value for
  210. the BeginScan command later:
  211.  
  212.     13    MXValue 3
  213.     14    IF RESULT = 0 THEN
  214.     15        scanType = "ALL"
  215.     16    ELSE
  216.     17        scanType = "SELECTED"
  217.  
  218. Save lines 1-17 in a file called "Requestor2.mxe", execute it, play with
  219. the gadgets, and see what happens.
  220.  
  221.     Now we are done with gadgets and user input, so it's time to do
  222. the actual transposition.
  223.  
  224.     18    Event. = ""
  225.     19    BeginScan scanType
  226.     20    NextEvent
  227.     21    DO WHILE RESULT = 1
  228.     22        IF Event.Type = "NOTE" THEN DO
  229.     23            Event.Num = Event.Num + semitones
  230.     24            IF add = 1 THEN
  231.     25                AddEvent
  232.     26            ELSE
  233.     27                ReplEvent
  234.     28        END
  235.     29        NextEvent
  236.     30    END
  237.  
  238.     Note how similar this is to the loop in Transposer.mxe.  The only
  239. differences are in lines:
  240.  
  241.     18.    Initialize the Event variable so we can add events.
  242.     19.    BeginScan is instructed to scan ALL or SELECTED events,
  243.         based on the user choice.
  244.     23.    We now add the value "semitones" instead of 7.
  245.     24-27.    Depending on the user's choice, we either add or replace
  246.         the notes we transpose.
  247.  
  248.     Put lines 1-30 in a file called NewTransposer.mxe, and have fun
  249. with this highly useful script!  If you try to transpose notes higher than
  250. MIDI allows (127), Music-X will "wrap then around" to 0 again; similarly
  251. for note numbers below 0.  A note of caution:  this script has very little
  252. error checking.  You really should check the value of RESULT after the
  253. BeginScan, AddEvent, and ReplEvent commands to make sure they worked.
  254.  
  255.  
  256. EXAMINING THE BAR EDITOR
  257.  
  258.     In this section, we will build a script for adding pitch bend to a
  259. marked or selected region.  Pitch bend events will be added, one at a time,
  260. at regular intervals in the region.  The user may define how far apart
  261. the pitch bend events are. When followed by Music-X's Sculpt tool, this
  262. script will let you create interesting pitch-bend shapes.
  263.  
  264.     Bar Editor information is examined by using the GetBarData command.
  265. This command fills in the variable "BarData" with information like the
  266. current grid size, measure size, beginning and end of a marked region, etc.
  267. GetBarData is used like this:
  268.  
  269.     1    /* Bar Data example with pitch bend events. */
  270.     2    OPTIONS RESULTS
  271.     3    GetBarData
  272.     4    IF RESULT = 0 THEN DO
  273.     5        MXReport "Could not get bar data."
  274.     6        EXIT
  275.     7    END
  276.  
  277. Next, we detect whether there is a region defined.
  278.  
  279.     8    IF BarData.Select = "NONE" THEN DO
  280.     9        MXReport "No region is marked/selected."
  281.     10        EXIT
  282.     11    END
  283.  
  284.     Save lines 1-11 to a file called "CheckRegion.mxe" and execute it.
  285. If no region is marked or selected, the script will display the MXReport
  286. requestor.
  287.  
  288.     Next, we allow the user to choose the spacing between the pitch
  289. bend events, using an MXNoteSize gadget, and the MIDI channel for the
  290. events, using a slider gadget.  We store the user's choices in the
  291. variables "spacing" and "midiChannel", respectively.
  292.  
  293.     12    MXNoteSize "Set Spacing:"
  294.     13    MXSlider "MIDI Channel:,1,16,1"
  295.     14    MXRequest "Add Pitch Bend Events"
  296.     15    IF RESULT = 0 THEN
  297.     16        EXIT
  298.     17    MXValue 1
  299.     18    spacing = RESULT
  300.     19    MXValue 2
  301.     20    midiChannel = RESULT - 1
  302.  
  303. The reason for "RESULT - 1" is that Music-X stores MIDI channels 1-16
  304. as 0-15 internally.  Add lines 12-20 to your script so you can see the
  305. requestor in Figure 2.
  306.  
  307.     Next, we locate the beginning and end of the region.  Time in
  308. Music-X is measured in bars (measures) and clocks (clock ticks in each
  309. measure).  For example, a note might appear in bar 17, clock 2475. 
  310. Information about bars and clocks is stored in the variables:
  311.  
  312.     BarData.Start.Bars    Measure number of the start of the region.
  313.     BarData.Start.Clocks    Clock number of the start of the region.
  314.     BarData.Stop.Bars    Measure number of the end of the region.
  315.     BarData.Stop.Clocks    Clock number of the end of the region.
  316.     BarData.Measure        Number of clocks per measure.
  317.  
  318.     We use our own variable "currentTime" to represent the current
  319. location in the region as we add events.  As the script progresses, we
  320. repeatedly add a number of clocks (stored in the "spacing" variable) to the
  321. current time.  However, when adding an event, we need to know the Bars and
  322. Clocks values, which will require a little math.
  323.  
  324.     Given the measure number and clock number of a Music-X event, the
  325. formula for calculating its location in clocks is:
  326.  
  327.         (Measure number) * (Clocks per Measure) + (Clock number)
  328.  
  329. Thus, in our script, we compute the starting and ending times of our
  330. region, in clocks:
  331.  
  332.     21    currentTime = BarData.Start.Bars * BarData.Measure    ,
  333.                   + BarData.Start.Clocks
  334.     22    endTime        = BarData.Stop.Bars  * BarData.Measure    ,
  335.                   + BarData.Stop.Clocks
  336.  
  337. (Note:  In ARexx, a comma means "continued on the next line."  If you can
  338. fit each command on one line -- not possible on this magazine page -- then
  339. you must omit the commas.)
  340.  
  341.     Next, we prepare to scan the region.  Just for fun, while the
  342. script is working, we change the pointer to the "sleeping cloud" to
  343. indicate work is being done.
  344.  
  345.     23    MXPointer "SLEEPY"
  346.     24    Event. = ""        /* Initialize Event variable */
  347.     25    BeginScan
  348.  
  349.     Since we are adding pitch bend events, we can fill in some of
  350. the Event variable fields that will remain constant:  the event type,
  351. the MIDI channel, and an event value (we choose +8192, which is zero
  352. pitch bend).
  353.  
  354.     26    Event.Type    = "PBEN"
  355.     27    Event.Channel    = midiChannel
  356.     28    Event.Num    = 8192
  357.  
  358.     Finally, it is time to add pitch bend events!  To add them at the
  359. right locations, we must calculate the Bar and Clock numbers where they
  360. should be added.  The bar number is obtained using integer division (the
  361. "%" operator), and the clock number using the "mod" or "remainder" function
  362. (the "//" operator):
  363.  
  364.     29    DO WHILE currentTime <= endTime
  365.     30        Event.Start.Bars   = currentTime %  BarData.Measure
  366.     31        Event.Start.Clocks = currentTime // BarData.Measure
  367.     32        AddEvent
  368.     33        currentTime        = currentTime + spacing
  369.     34    END
  370.  
  371. When the loop is done, clean up and exit.
  372.  
  373.     35    EndScan
  374.     36    MXPointer "NORMAL"
  375.  
  376.     Save lines 1-36 in a file called "PitchBend.mxe". To use this
  377. script, first mark a region or select some events.  Second, run the
  378. PitchBend.mxe script.  Third, use the Sculpt Tool to shape the pitch bend
  379. events the way you want them. Enjoy!
  380.  
  381.     Note:  RexxEdit has a bug concerning marked regions.  If a region
  382. appears to be marked, but you keep getting the requestor "No region is
  383. marked/selected," try marking the region again or using the Select tool
  384. instead of Mark.  (See "TECH TALK" below for more information.)
  385.  
  386.     Another note:  the above assumes you are using "relative time"
  387. sequences, not "absolute time" sequences.  If you use absolute time
  388. sequences, then time is measured in quarter frames instead of clocks;
  389. see the manual for more information.
  390.  
  391.  
  392. COMMUNICATING WITH OTHER PROGRAMS
  393.  
  394.     Using the ARexx "ADDRESS" command, Music-X scripts can talk to
  395. other ARexx-compatible products such as Deluxe Music 2.0, Bars and Pipes
  396. Professional, One Stop Music Shop, and even non-music products.  How about
  397. using SuperBase Professional to store your Music-X sequences?  VLT for
  398. uploading and downloading sequences?  AmigaVision for multimedia?  The
  399. possibilities are numerous and exciting.
  400.  
  401.     Communicating with another program has 4 steps.
  402.  
  403.     1. Find out the ARexx port names of the other program, by
  404.        consulting its documentation.
  405.  
  406.     2. Store Music-X's port name in a variable for safekeeping,
  407.        using the Address() command.  (See "TECH TALK", below,
  408.        if you are interested in the reason.)
  409.  
  410.     3. Use the Show("P") command to make sure that the other programs
  411.        are running.  If not, then your script run them, using the
  412.        "WaitForPort" command to wait until the program is running.
  413.  
  414.     4. Use the "ADDRESS" command to talk to the other programs.
  415.  
  416.     In this section, we write scripts to communicate with Electronic
  417. Arts' Deluxe Music 2.0 notation program, port name "DMUSIC", and Oxxi's
  418. TurboText editor, port name "TURBOTEXT".  Our first script sends the
  419. currently selected Music-X note to Deluxe Music, inserting it at Deluxe
  420. Music's current cursor location.
  421.  
  422.     First, we save Music-X's port name in a variable "myAddress":
  423.  
  424.     1    /* Example script using Deluxe Music 2.0. */
  425.     2    OPTIONS RESULTS
  426.     3    myAddress = Address()
  427.  
  428. Next, we make sure that something is selected.
  429.  
  430.     4    GetBarData
  431.     5    IF BarData.Select ~= "SELECT" THEN DO
  432.     6        MXReport "Nothing is selected."
  433.     7        EXIT
  434.     8    END
  435.  
  436. Next, we make sure that the selected event is a note.
  437.  
  438.     9    BeginScan "SELECTED"
  439.     10    NextEvent
  440.     11    EndScan
  441.     12    IF Event.Type ~= "NOTE" THEN DO
  442.     13        MXReport "You must select a note."
  443.     14        EXIT
  444.     15    END
  445.  
  446.     Next, we make sure Deluxe Music is running by looking for its
  447. ARexx port.  If a port named "DMUSIC" does not exist, then we run
  448. Deluxe Music.
  449.  
  450.     16    IF ~Show('P', 'DMUSIC') THEN DO
  451.     17        ADDRESS COMMAND 
  452.     18        "Run < NIL: > NIL: DMusic"
  453.     19        WaitForPort "DMUSIC"
  454.     20    END
  455.  
  456. Now, we are ready to send the note from Music-X to Deluxe Music.
  457.  
  458.     21    ADDRESS "DMUSIC" 
  459.     22    INSERTITEM NOTE PITCH Event.Num
  460.     23    NEXT NOTE
  461.  
  462.     Finally, we pop the Deluxe Music screen to the front to see our
  463. handiwork:
  464.  
  465.     24    SCREENTOFRONT
  466.  
  467.     Save lines 1-24 to a file called "DMusic.mxe", execute the script,
  468. and watch what happens.  With some work, this script could be the basis for
  469. a whole direct interface between Music-X and Deluxe Music. You may notice
  470. that we didn't use the myAddress variable.  This is because the script did
  471. all its Music-X communication first, and then all its Deluxe Music
  472. communication.
  473.  
  474.     The next example is more complex, sending information about notes
  475. and their velocities from a sequence into a TurboText edit window.  We
  476. start off with the usual, saving Music-X's address and invoking TurboText
  477. if it is not running:
  478.  
  479.     1    /* Send note information to TurboText. */
  480.     2    OPTIONS RESULTS
  481.     3    myAddress = Address()
  482.     4    IF ~Show("P", "TURBOTEXT") THEN DO
  483.     5        ADDRESS COMMAND
  484.     6        "TTX > NIL: BACKGROUND NOWINDOW"
  485.     7        WaitForPort "TURBOTEXT"
  486.     8    END
  487.  
  488.     Next, we tell TurboText to open a new edit window.  The name of
  489. that window (its own ARexx port) is returned in the RESULT variable:
  490.  
  491.     9    ADDRESS "TURBOTEXT"
  492.     10    OpenDoc
  493.     11    windowName = RESULT
  494.  
  495.     Finally, we talk to Music-X again, scan through the sequence,
  496. picking out notes, and sending their information to the TurboText window:
  497.  
  498.     12    ADDRESS VALUE myAddress
  499.     13    BeginScan ALL
  500.     14    NextEvent
  501.     15    DO WHILE RESULT = 1
  502.     16        IF Event.Type = "NOTE" THEN DO
  503.     17            ADDRESS VALUE windowName
  504.     18            Insert "Note" Event.Num "Vel" Event.Attack
  505.     19            InsertLine
  506.     20            ADDRESS VALUE myAddress
  507.     21        END
  508.     22        NextEvent
  509.     23    END
  510.     24    EndScan
  511.  
  512.     I realize that these Deluxe Music and TurboText scripts are harder
  513. to understand than the previous ones.  This is because each program has its
  514. own set of commands, such as "OpenDoc" and "Insert" in the TurboText example.
  515. Writing scripts that connect two programs means learning the command sets for
  516. both programs, and this may require careful reading of each program's
  517. documentation, as well as a lot of hair pulling!
  518.  
  519.  
  520. REXXEDIT TIPS AND TRICKS
  521.  
  522.     Here is a set of (mostly undocumented) tips and tricks I've
  523. discovered while writing Music-X scripts.
  524.  
  525. o    The MXReport command is great for helping to debug your scripts.
  526.     If you want to see the value of a variable (say, "myVar") at any
  527.     time, just insert the line "MXReport myVar" at the appropriate spot
  528.     in the script.  If you need more space for messages, use MXLabel
  529.     and MXRequest.
  530.  
  531. o    If your gadgets in an MXRequest don't have enough space between
  532.     them for your tastes, the command
  533.  
  534.         MXLabel ""
  535.  
  536.     will insert a blank line.  Remember to count this MXLabel
  537.     command when using MXValue to read gadget values!
  538.  
  539. o    By default, the RexxEdit module is available only inside the Bar
  540.     and Event Editors.  But you can use the "Install Modules" script
  541.     to make it available in other pages.  Simply click on the
  542.     other checkboxes in the "Install Modules" window, quit and
  543.     restart Music-X, and you're set.  The ARexx functionality will
  544.     be more limited on other pages, because there is no "current
  545.     sequence" being displayed, but you can still do some interesting
  546.     things.
  547.  
  548. o    The "Event" variable has different fields depending on what
  549.     type of event it contains.  For example, a NOTE event has its
  550.     velocity in Event.Attack, but it does not use Event.Pressure.
  551.     You must write your scripts carefully so they examine ONLY
  552.     the Event fields that apply to the current event.  Read pages
  553.     49-52 carefully to learn which event fields are valid.
  554.     (See also the next item.)
  555.  
  556. o    The spacing and boldfacing on pages 49 and 50 of the Music-X 2.0
  557.     Upgrade Manual is messed up, making it difficult to distinguish
  558.     event types from variables.  Four variable names are incorrectly
  559.     boldfaced:  EVENT.DEM belongs to the TSIG event, EVENT.TRANSPOSE
  560.     and EVENT.CUT belong to the PSEQ event, and EVENT.ATTACK belongs
  561.     to the NOTE event.
  562.  
  563. o    The range of pitch bend values goes from -8192 to +8191, with
  564.     0 being zero pitch bend.  PBEN event values
  565.     (Event.Num) are really between 0 and 16383; that
  566.     is, 8192 higher than the actual bend value.  If you use an MXMirror
  567.     gadget to get pitch bend values from the user, remember to
  568.     add 8192 to the result before storing it in Event.Num.
  569.  
  570. o    Since pitch bend goes from -8192 to +8191, not +8192.  If you use an
  571.     MXMirror slider for pitch bend, the highest positive value +8192
  572.     is invalid.  So your script may need code like this:
  573.  
  574.         MXValue 3          /* Get the MXMirror value. */
  575.         value = RESULT
  576.         IF value = 8192 THEN      /* Disallow +8192 value.   */
  577.             value = 8191
  578.  
  579.  
  580. REXXEDIT PROBLEMS
  581.  
  582.     One of RexxEdit's omissions is that it has no ARexx command for
  583. disabling user input.  While a script is running, all gadgets on the Music-X
  584. screen are "live," even though they do not appear to respond, and they will
  585. react to all of your inadvertent keystrokes and mouseclicks when the script
  586. finishes.  So, while a script is executing, don't click on any gadgets
  587. except those in an ARexx requestor (e.g., MXRequest).  As a visual aid, do
  588. "MXPointer SLEEPY" while a script is running.
  589.  
  590.     Second, RexxEdit cannot abort a script in progress.  Suppose your
  591. script scans a sequence with a loop, but you forget to call NextEvent in
  592. it.  You now have an infinite loop and no way to stop it except by
  593. rebooting your Amiga.
  594.  
  595.     Third, as mentioned earlier, Music-X "forgets" any marked region
  596. every time RexxEdit is run.  This is especially confusing because the
  597. region on the screen still appears to be marked.  The problem does not
  598. occur with selected events. To get around this problem, either use
  599. selecting instead of marking when possible, or re-mark the region after
  600. each ARexx macro is run.  There is also a problem with the selected
  601. events.  The Select tool works fine.  However, if you use the Move or Add
  602. tools and click on an event, it highlights as if it were selected.  Other
  603. modules like the Quantizer will treat it as selected.  However, RexxEdit
  604. does not think it is selected.  The moral:  if a script requires selected
  605. events, you must use the Select tool.
  606.  
  607.  
  608. TECH TALK
  609.  
  610.     If you've used ARexx before, you may notice that Music-X's
  611. interface is unusual in several notable ways.  First, its ARexx port name
  612. is completely undocumented.  By using the command
  613.  
  614.         MXReport Address()
  615.  
  616. I discovered that the name is "MUSIC-X AREXX EDIT". However, this
  617. information is of no use, because of a second non-standard feature:  it's
  618. impossible to control Music-X from another program.  All scripts must be
  619. run from inside Music-X.  This is because the ARexx port belongs to
  620. RexxEdit, not to Music-X. When RexxEdit is not running, the port
  621. disappears, and when RexxEdit is running, Music-X occupies its full
  622. attention.
  623.  
  624.     A third oddity involves ARexx return codes.  By convention, ARexx
  625. commands return their success (1) or failure (0) values in the "RC"
  626. variable.  Music-X uses the "RESULT" variable instead, which is usually
  627. reserved for more complex return values.  RC is unused.  Until you figure
  628. this out, you'll be scratching your head wondering why your error-checking
  629. doesn't work.
  630.  
  631.  
  632. GOOD LUCK!
  633.  
  634.     By using ARexx and RexxEdit, you can personalize Music-X with
  635. powerful new tools of your own invention.  It takes some effort to get
  636. used to ARexx, but the results can really be worth it.
  637.  
  638. ===
  639.  
  640. Daniel J. Barrett has been making electronic and computer music since
  641. 1979, and has been an Amiga owner since 1987.
  642.